use std::io;
use std::ops::{Deref, DerefMut};
use std::sync::atomic::AtomicBool;
use anyhow::Result;

use crossterm::{Command , 
                event::{DisableBracketedPaste ,  DisableMouseCapture,  EnableBracketedPaste ,  EnableMouseCapture , 
                        KeyboardEnhancementFlags , PopKeyboardEnhancementFlags , PushKeyboardEnhancementFlags} , 
                execute , queue , style::Print , 
                terminal::{EnterAlternateScreen , LeaveAlternateScreen , SetTitle , disable_raw_mode , enable_raw_mode , } ,
};
use ratatui::{CompletedFrame ,  Frame , Terminal , backend::CrosstermBackend , buffer::Buffer , layout::Rect }; 
use jizi_shared::SyncCell ;
use jizi_term::tty::{TTY , TtyWriter} ;
use jizi_adapter::{TMUX} ;
static CSI_U : AtomicBool = AtomicBool::new(false) ;  // 这干啥的？

pub (super) struct Term {
    inner : Terminal<CrosstermBackend<TtyWriter<'static>>> ,
    last_area : Rect  , 
    last_buffer : Buffer,
}


impl Term {
    pub (super) fn start() -> Result<Self> {
        static SKIP : SyncCell<bool> = SyncCell::new(false) ;
        let mut term = Self{
            inner : Terminal::new(CrosstermBackend::new(TTY.writer()))? ,
            last_area : Default::default() ,
            last_buffer : Default::default() ,
        } ;
        enable_raw_mode() ;

        // todo tmux support
        // if SKIP.replace(true) && jizi_adapter::TMUX.get() {
        //     jizi_adapter::Mux::tmux_passthrough() ;
        // }
        // execute!(
        //     TTY.writer() ,
        //     jizi_term::If(!TMUX.get() , EnterAlternateScreen) ,
        //     Print("\x1bP$q q\x1b\\") ,
        //     jizi_term::If(TMUX.get() , EnterAlternateScreen) ,
        //     EnableBracketedPaste ,
        //     jizi_term::If(!JIZI.mgr.mouse_events.is_empty() , EnableMouseCapture) ,
        // )? ;
        // let resp = Emulator::read_util_da1() ;
        term.hide_cursor()? ;
        term.clear()? ;
        term.flush()? ;
        Ok(term)
    }
    
    fn stop(&mut self) -> Result<()> {
        self.show_cursor()? ;
        Ok(disable_raw_mode()?)
    }
    
    pub(super) fn goodbye(f : impl FnOnce() -> i32) -> ! {
        disable_raw_mode().ok() ;

        std::process::exit(f()) ;
    }
    
    
    pub(super) fn draw(&mut self, f : impl FnOnce(&mut Frame)) -> io::Result<(CompletedFrame)>{
        let last = self.inner.draw(f) ? ;
        self.last_area = last.area ; 
        self.last_buffer = last.buffer.clone();
        Ok(last) 
    }

    pub (super) fn draw_partial(&mut self, f : impl FnOnce(&mut Frame)) -> io::Result<CompletedFrame> {
        self.inner.draw(|frame| {
            let buffer = frame.buffer_mut();
            for y in self.last_area.top() .. self.last_area.bottom() {
                for x in self.last_area.left() .. self.last_area.right() {
                    let mut cell = self.last_buffer[(x,y)].clone() ;
                    cell.skip = false ;
                    buffer[(x,y)] = cell ;
                }
            }
            f(frame) ;
        })
    }
    #[inline]
    pub (super) fn can_partial(&mut self) -> bool {
        self.inner.autoresize().is_ok() && self.last_area == self.inner.get_frame().area()
    }
}

impl Drop for Term {
    fn drop(&mut self) {
        self.stop().ok() ;
    }
}

impl Deref for Term {
    type Target = Terminal<CrosstermBackend<TtyWriter<'static>>> ; 
    fn deref(&self) -> &Self::Target {
        &self.inner 
    }
}

impl DerefMut for Term {
    // 你可以注意到 这里没有重新声明Type 而是直接用了Target
    // 这是因为DerefMut是继承了Deref  天然拥有Deref的所有约束和关联类型
    // 所以DerefMut继承了Deref  共享同一个Target  所以不需要也不允许重复声明
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.inner 
    }
}

#[cfg(test)]
mod tests {
    use std::thread;
    use std::time::Duration;
    use super::*;
    use crossterm::{
        execute,
        terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
    };
    use ratatui::{backend::CrosstermBackend, Terminal as RatatuiTerminal, Frame, layout::Rect};
    use atty:: is ;
    use atty::Stream::Stdout;
    #[test]
    fn test_atty_detection() -> io::Result<()> {
    
        // 检查标准输出是否为 TTY
        let is_stdout_tty = is(atty::Stream::Stdout);
        println!("Is stdout a TTY? {}", is_stdout_tty);
    
        // 检查标准输入是否为 TTY
        let is_stdin_tty = is(atty::Stream::Stdin);
        println!("Is stdin a TTY? {}", is_stdin_tty);
    
        Ok(())
    }
    
    #[test]
    fn setup_terminal() -> io::Result<()> {
        if !is(atty::Stream::Stdout) {
            return Err(io::Error::new(
                io::ErrorKind::Other,
                "Not running in an interactive terminal",
            ));
        }
        enable_raw_mode().expect("Failed to enable raw mode");
        execute!(io::stdout(), EnterAlternateScreen).expect("Failed to enter alternate screen");

        Ok(())
    }

    fn teardown_terminal() -> io::Result<()> {
        execute!(io::stdout(), LeaveAlternateScreen)?;
        disable_raw_mode()?;
        Ok(())
    }
    #[test]
    fn test_terminal_setup_and_teardown() -> io::Result<()> {
        // 设置终端
        setup_terminal().expect("Failed to set up terminal");

        // 模拟测试逻辑
        println!("Entered alternate screen. Waiting for 5 seconds...");

        // 添加延迟，观察备用屏幕效果
        thread::sleep(Duration::from_secs(5));

        // 恢复终端
        teardown_terminal().expect("Failed to tear down terminal");

        Ok(())
    }

}